using System;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Comteck.Dto;
using Comteck.Extensions;
using Comteck.Ktt.Base;
using Comteck.Ktt.WinUI.Goods;
using Comteck.Ktt.WinUI.Orders;
using Comteck.Ktt.WinUI.Sys;
using Comteck.TenantSystem.Services;
using Comteck.Utils;
using Comteck.Winforms;
using Comteck.Winforms.Data;
using Comteck.Winforms.Forms;
using Comteck.Winforms.Utils;
using log4net;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Win32;
using WinApp = System.Windows.Forms.Application;

namespace Comteck.TenantSystem {
  static class Program {
    /// <summary>
    /// 
    /// </summary>
    private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    /// <summary>
    /// 应用程序的主入口点。
    /// </summary>
    [STAThread]
    static void Main(string[] args) {
      // dev皮肤设置
      DevHelper.RegisterSkins();
      // 
      WinApp.EnableVisualStyles();
      WinApp.SetCompatibleTextRenderingDefault(false);

      #region 加载系统相关设置

      // 捕捉应用程序异常
      WinformStartUpHelper.CatchException();

      // log4net
      Log4NetHelper.Load();

      // 0、加载app.config
      LoadStep(SysGlobal.LoadAppSettings, "配置文件");

      // 0、更新update文件
      LoadStep(SysGlobal.ReplaceUpdateExe, "Update文件");

      // 加载动画效果
      WinformHelper.ShowLoadScreen();

      // 加载log4net
      WinformHelper.SendLoadScreenCommand(LoadWaitScreenCommand.ChangeTitle, "正在加载日志……");
      Log4NetHelper.DeleteFiles("logs", 2);

      log.Info("【应用程序】 启用开始");

      // 1、检查同一目录的应用程序是否有启动
      if (WinformHelper.IsProcessExistsBySameDirectory(out var existProcess)) {
        var msg = $"该目录下的应用程序已经启动！{Environment.NewLine}如果您想启动多个，请拷贝一份程序到不同的目录下，并点击取消{Environment.NewLine}如果您想直接启动，请确保已启动的程序资源已保存，并点击确定";
        if (MessageBox.Show(msg,
          null, MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK) {
          // 确定：杀掉已经运行的另外一个进程
          KillProcess(existProcess);
        } else {
          // 取消：退出
          SysGlobal.Close(true);
          return;
        }

      }


      // 2.1、设置皮肤
      DevHelper.SetSkin(SysGlobal.Settings.Dev_SkinName);

      // 加载Logo图片
      var logoPath = $@"{WinApp.StartupPath}\{SysGlobal.Settings.LogoPath}";
      if (File.Exists(logoPath)) {
        try {
          SysGlobal.LogoImage = Image.FromFile(logoPath);
        } catch (Exception ex) {
          log.Error("加载Logo图片失败", ex);
        }
      }

      // 3、初始化数据库结构
      LoadStep(() => {
        LoadDatabase();
      }, "数据库结构", false);

      // 4、初始化全局信息
      LoadStep(() => {
        SysGlobal.LoginFormType = typeof(FrmLogin);
        SysGlobal.Initialize((services) => {
          services.AddTransient<FrmLogin>();
          services.AddTransient<FrmMain>();
          services.AddTransient<FrmDashboard>();

          services.AddTransient<FrmParameterAdmin>();
          services.AddTransient<FrmPrintTemplateAdmin>();
          services.AddTransient<FrmPrintTemplateAction>();

          services.AddTransient<ProductAdmin>();
          services.AddTransient<ProductAction>();
          services.AddTransient<FrmProductBatchAction>();

          services.AddTransient<FrmSelfOrgTagAdmin>();
          services.AddTransient<FrmSelfOrgTagAction>();

          services.AddTransient<FrmSelfOrgAdmin>();
          services.AddTransient<FrmSelfOrgAction>();
          services.AddTransient<FrmSelfOrgDialog>();
          services.AddTransient<FrmSelfOrgBatchAction>();

          services.AddTransient<FrmSaleOrderAdmin>();
          services.AddTransient<FrmSaleOrderDetailSplitAction>();
          services.AddTransient<FrmSaleOrderRecycleAdmin>();
        });
      }, "初始化数据");

      // 4、控件汉化
      LoadStep(() => DevHelper.SetLocalizer(), "系统模块");

      // FR控件设置语言包
      FastReport.Utils.Res.LocaleFolder = WinApp.StartupPath;
      FastReport.Utils.Res.LoadLocale(FastReport.Utils.Res.LocaleFolder + @"\Chinese (Simplified).frl");

      #endregion

      // 校验版本信息
      var form = SysGlobal.ServiceProvider.GetRequiredService<FrmLogin>();

      log.Info("【应用程序 启用结束");

      form?.Activate();

      if (form != null) {
        var context = new ApplicationContext(form);
        OpenLoadForm(context);
      } else {
        SysGlobal.Close();
      }

      // WindowsFormsSynchronizationContext
      // https://www.cnblogs.com/songxingzhu/p/5343905.html
    }

    private static Rectangle currentBounds;
    private static Screen currentScreen;
    private static void OnDisplaySettingsChanged(object sender, EventArgs e) {
      var screen = Screen.FromControl(WinApp.OpenForms[0]);
      var bounds = screen.Bounds;
      if (screen.DeviceName == currentScreen.DeviceName && currentBounds.Width == bounds.Width) {
        return;
      }
      var currentContext = System.Threading.SynchronizationContext.Current;
      if (currentContext != null) {
        currentContext.Post((state) => {
          var form = WinApp.OpenForms.OfType<FrmDisplaySettingChanges>().FirstOrDefault();
          if (form == null) {
            form = new FrmDisplaySettingChanges();
            var result = form.ShowDialog();
            if (result == DialogResult.OK) {
              try {
                WinformHelper.SetFormsConfirmedClosed();
              } catch {
              }
              WinApp.Restart();
            }
          } else {
            form.Activate();
            form.BringToFront();
          }
        }, null);
      }
    }

    /// <summary>
    /// 删除进程
    /// </summary>
    /// <param name="name"></param>
    private static void KillProcess(Process process) {
      // 删除进程
      try {
        process.Kill();
        process.Close();
      } catch {
      }
    }

    /// <summary>
    /// 初始化数据库脚本（还需要处理）
    /// </summary>
    private static void LoadDatabase() {
      try {
        LocalDbContainer.Init();
      } catch (Exception ex) {
        log.Info(null, ex);
      }
    }

    #region 校验版本信息

    /// <summary>
    /// 启动主程序
    /// </summary>
    private static void OpenLoadForm(ApplicationContext applicationContext) {
      var formName = applicationContext.MainForm?.Text;

      try {
        // run
        WinformHelper.SendLoadScreenCommand(LoadWaitScreenCommand.ChangeTitle, "正在打开启动窗口……");
        log.Info($"窗口 【{formName}】 加载成功");
        //监听dpi变化
        currentScreen = Screen.PrimaryScreen;
        currentBounds = currentScreen.Bounds;
        SystemEvents.DisplaySettingsChanged += OnDisplaySettingsChanged;

        WinApp.Run(applicationContext);
      } catch (Exception ex) {
        log.Error($"窗口 【{formName}】 加载失败", ex);
        DevHelper.ShowMsg(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
      }
    }

    #endregion

    #region 加载步骤

    /// <summary>
    /// 
    /// </summary>
    /// <param name="action"></param>
    /// <param name="title"></param>
    /// <param name="onErrorExit"></param>
    private static void LoadStep(Action action, string title, bool onErrorExit = true) {
      WinformHelper.SendLoadScreenCommand(LoadWaitScreenCommand.ChangeTitle, $"正在加载 {title} ……");
      try {
        log.Info($"【{title}】 加载开始");
        action();
        log.Info($"【{title}】 加载结束");
      } catch (Exception ex) {
        WinformHelper.SendLoadScreenCommand(LoadWaitScreenCommand.ChangeTitle, $"加载 {title} 失败……");
        log.Info($"【{title}】 加载失败", ex);

        if (onErrorExit) {
          ExitSystem();
        }
      }
    }

    /// <summary>
    /// 
    /// </summary>
    private static void ExitSystem() {
      System.Threading.Thread.Sleep(1000);
      SysGlobal.Close();
      Environment.Exit(0);
      //WinApp.Exit();
    }

    #endregion

  }
}
